﻿﻿using DeviceCommons.DataHandling;
using DeviceCommons.DeviceMessages.Models;
using DeviceCommons.DeviceMessages.Models.V1;
using DeviceCommons.DeviceMessages.Serialization.V1.Serializers;
using DeviceCommons.Validation;
using System.Buffers;

namespace DeviceCommons.DeviceMessages.Serialization.V1
{
    public class ProcessVersionData : IProcessVersion
    {
        public void Parser(IDeviceMessage model, ReadOnlySpan<byte> bytes)
        {
            ArgumentNullException.ThrowIfNull(model);

            int index = 4;
            int mainDeviceLength = CalculateMainDeviceDataLength(bytes, index);
            if (mainDeviceLength > 0)
            {
                byte[] mainDeviceData = bytes.Slice(index, mainDeviceLength).ToArray();
                model.MainDevice = DeviceMessageSerializerProvider.InfoV1Par.Parser(mainDeviceData);
                index += mainDeviceLength;
            }

            int childDeviceLength = bytes.Length - index;
            if (childDeviceLength < 0) 
                throw new DeviceMessageValidationException(
                    ValidationErrorType.InvalidChildDeviceDataLength,
                    "子设备数据长度无效，主设备数据可能损坏",
                    nameof(bytes),
                    "非负数的数据长度",
                    childDeviceLength);

            if (childDeviceLength > 0)
            {
                byte[] childDeviceData = bytes.Slice(index, childDeviceLength).ToArray();
                model.ChildDevice = DeviceMessageSerializerProvider.ChildV1Par.Parser(childDeviceData);
                index += childDeviceLength;
            }
        }

        public ReadOnlySpan<byte> Serializer(IDeviceMessage model)
        {
            ArgumentNullException.ThrowIfNull(model);
            var arrayBufferWriter = new ArrayBufferWriter<byte>();
            DeviceMessageSerializerProvider.ChildV1Ser.Serializer(arrayBufferWriter, model.ChildDevice ?? new DeviceMessageChild());
            DeviceMessageSerializerProvider.InfoV1Ser.Serializer(arrayBufferWriter, model.MainDevice ?? new DeviceMessageInfo());
            DeviceMessageSerializerProvider.HeaderV1Ser.Serializer(arrayBufferWriter, model.Header ?? new DeviceMessageHeader());
            return arrayBufferWriter.WrittenSpan;
        }

        private static int CalculateMainDeviceDataLength(ReadOnlySpan<byte> bytes, int startIndex)
        {
            int index = startIndex;
            if (index >= bytes.Length) return 0;
            byte didLength = bytes[index++];
            index += didLength;
            if (index >= bytes.Length) return index - startIndex;
            index++;
            if (index >= bytes.Length) return index - startIndex;
            byte readingCount = bytes[index++];
            for (int i = 0; i < readingCount; i++)
            {
                if (index + 2 > bytes.Length) return bytes.Length - startIndex;
                index += 2;
                if (index >= bytes.Length) break;
                byte stateCount = bytes[index++];
                for (int j = 0; j < stateCount; j++)
                {
                    if (index + 2 > bytes.Length)
                        return bytes.Length - startIndex;
                    byte sid = bytes[index++];
                    byte type = bytes[index++];
                    int valueLength = DeviceMessageUtilities.GetValueLength(bytes, index - 1);
                    if (index + valueLength > bytes.Length)
                        return bytes.Length - startIndex;
                    index += valueLength;
                }
            }
            return index - startIndex;
        }
    }
}
